package com.yty.system.oauth.config.jwt;

import com.yty.system.oauth.entity.SysUser;
import com.yty.system.oauth.entity.vo.SecurityUser;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class UserAuthenticationConverter extends DefaultUserAuthenticationConverter {

    private Collection<? extends GrantedAuthority> defaultAuthorities;

    public void setDefaultAuthorities(String[] defaultAuthorities) {
        this.defaultAuthorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.arrayToCommaDelimitedString(defaultAuthorities));
    }

    private static final String USER_INFO = "userInfo";

    /**
     * 设置存入认证信息中的Map
     *
     * @param authentication
     * @return
     */
    @Override
    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
        // 入参authentication中保存了完整的用户信息（都已经有完整信息了还查个P）。
        Map<String, Object> map = new HashMap<>(1);
        // 获取用户信息并保存。
        Object o = authentication.getPrincipal();
        SecurityUser userInfo = (SecurityUser) o;
        SysUser sysUser = userInfo.getSysUser();
        map.put(USER_INFO, sysUser);
        // 保存了账户的权限信息，可以通过Authentication..getAuthorities()方法获取。
        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
            map.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
        }
        return map;
    }

    /**
     * 选择存入认证信息中的数据
     *
     * @param map
     * @return
     */
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        Authentication authentication = null;
        if (map.containsKey(USER_INFO)) {
            // 将用户对象作为用户信息。
            Object principal = map.get(USER_INFO);
            Collection<? extends GrantedAuthority> authorities = this.getAuthorities(map);
            authentication = new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
        }
        return authentication;
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        if (!map.containsKey(AUTHORITIES)) {
            return this.defaultAuthorities;
        } else {
            Object authorities = map.get(AUTHORITIES);
            if (authorities instanceof String) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList((String)authorities);
            } else if (authorities instanceof Collection) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection)authorities));
            } else {
                throw new IllegalArgumentException("Authorities must be either a String or a Collection");
            }
        }
    }
}
